<?php

defined('_JEXEC') or die();

jimport('joomla.installer.helper');
jimport('joomla.installer.installer');
require_once JPATH_COMPONENT.DS.'helpers'.DS.'XmlParser.php';
require_once JPATH_COMPONENT.DS.'helpers'.DS.'ftpHelper.php';

class ExtensionsHelper {

	var $repoDir;
	var $db;
	var $parser;
	var $installer;
	var $extractdir;
	var $xmlFile;
	var $extensionName;
	var $extensionNames = array();
	var $counter = 0;
	var $replaceString;
	var $selectedPackages;
	var $remotePackageName;
	var $instanceName;

	function __construct($repoDir) {

		$this->repoDir = $repoDir;
		$this->db =& JFactory::getDBO();
		$this->parser =& new XmlParser();

		$this->installer =& new JInstaller(); //JInstaller starts the actual installation process

		$this->replaceString = "|";
	}

	function setSelectedPackages($selected) {
		$this->selectedPackages = $selected;
	}

	function collectExtensionNames($name) {
		$this->extensionNames[$this->counter] = $name;
		$this->counter++;
	}

	/**
	 * unpacks the parameter packagefile path and returns if this extension is installed
	 *
	 * @param $packagepath
	 */
	function unpack($packagepath) {

		// We check with the easi table, if an entry for the package is set. If not, we unpack the package and store data in the easiv2 table.
		$this->db->setQuery("SELECT packagefile FROM #__easiv2 WHERE packagefile='".str_ireplace(DS, $this->replaceString, $packagepath)."'");
		$result = $this->db->loadObject();

		// unpack if not in the database
		if(count($result) == 0)
		{
			//			echo "unpacking: ".$packagepath."<br>";
			$foldername = JInstallerHelper::unpack($packagepath); //$helper->unpack() returns an array with two fields in it: 'extractdir' and 'packagefile'

			$this->extractdir = $foldername['extractdir'];

			$this->saveManifest();

			$extensionName = $this->parser->getNode(JPATH_COMPONENT.DS.$this->repoDir.DS."manifest".DS.$this->xmlFile[0], "/install/name");
			$type = $this->parser->getExtensionType(JPATH_COMPONENT.DS.$this->repoDir.DS.'manifest'.DS.$this->xmlFile[0]);

			//			echo "Saving: ".$extensionName."<br>";
			$this->extensionName = $extensionName;

			$this->db->setQuery("INSERT INTO #__easiv2(extension, type, packagefile, xmlFile) VALUES ('".$extensionName."', '".$type."', '".str_ireplace(DS, $this->replaceString, $packagepath)."', '".$this->xmlFile[0]."')");
			$this->db->query();

			JFolder::delete($this->extractdir);
		}
		else {
			$this->db->setQuery("SELECT extension FROM #__easiv2 WHERE packagefile='".str_ireplace(DS, $this->replaceString, $packagepath)."'");
			$result = $this->db->loadObject();

			$this->extensionName = $result->extension;
		}

		$this->collectExtensionNames($result->extension);

		$isInstalled = $this->isInstalled();
		return $isInstalled;
	}

	function getExtensionName() {
		return $this->extensionName;
	}

	function saveManifest() {

		if(!JFolder::exists(JPATH_COMPONENT.DS.$this->repoDir.DS.'manifest')) {
			JFolder::create(JPATH_COMPONENT.DS.$this->repoDir.DS.'manifest');
		}

		//Folder in which the manifest file has to be
		$folderForXml = JFolder::folders($this->extractdir);

		/*
		 * Most extensions have one folder after the unpacking, usually named as the extension itself. In this folder we can find the xml file.
		 * Some, like the Phoca Guestbook, have no folder with it's name. They have the whole MVC structure after unpacking.
		 * So the xml has to be found in the unpacked folder.
		 */
		if(count($folderForXml) > 1) //If more than one folder after unpacking is found, the xml file is in the unpack folder itself
		{
			$this->xmlFile = JFolder::files($this->extractdir, ".xml");

			/*
			 * Some extensions have additional xml files, like config.xml. These are not the manifest files, so we "filter" them out.
			 * We assume that most extension have only one config.xml, so we simply check, if the file does not equal config.xml
			 */
			if(count($this->xmlFile > 1))
			{
				for($j = 0; $j<count($this->xmlFile); $j++)
				{
					if($this->xmlFile[$j] != "config.xml")
					{
						$xmlFileReal = $this->xmlFile[$j];
					}
				}

				JFile::copy($this->extractdir.DS.$xmlFileReal, JPATH_COMPONENT.DS.$this->repoDir.DS."manifest".DS.$xmlFileReal);
				$this->xmlFile[0] = $xmlFileReal;
			}
			else
			{
				JFile::copy($this->extractdir.DS.$this->xmlFile[0], JPATH_COMPONENT.DS.$this->repoDir.DS."manifest".DS.$xmlFile[0]);
			}
		}
		else
		{
			$this->xmlFile = JFolder::files($this->extractdir, ".xml");

			if(count($this->xmlFile) == 0)
			{
				$this->xmlFile = JFolder::files($this->extractdir.DS.$folderForXml[0], ".xml");
				JFile::copy($this->extractdir.DS.$folderForXml[0].DS.$this->xmlFile[0], JPATH_COMPONENT.DS.$this->repoDir.DS."manifest".DS.$this->xmlFile[0]);
			}
			else
			{
				$this->xmlFile = JFolder::files($this->extractdir, ".xml");
				JFile::copy($this->extractdir.DS.$this->xmlFile[0], JPATH_COMPONENT.DS.$this->repoDir.DS."manifest".DS.$this->xmlFile[0]);
			}
		}
	}

	function isInstalled()
	{
		//get Extension type to determine, if it's already installed
		//		echo "looking for ".$this->extensionName."<br>";
		$this->db->setQuery("SELECT name FROM #__extensions WHERE name = '".$this->extensionName."'");

		$result = $this->db->loadObject();
			
		if(count($result) != 0) {
			return "true";
		}
		else {
			return "false";
		}
	}

	function install() {

		if(count($this->selectedPackages) > 0) {
			//table for better formatting with image on summary page
			echo '<table>';
			//Unpack and install
			for($i=0;$i<count($this->selectedPackages); $i++)
			{
				/**
				 * The values of the form come in the following format: "ExtensionName:InstanceToInstallIn"
				 */
				$instructions = split(":", $this->selectedPackages[$i]);

				$this->instanceName = $instructions[1];

				$this->db->setQuery("SELECT packagefile FROM #__easiv2 WHERE extension = '".$instructions[0]."'");
				$tempPackagefile = $this->db->loadObject()->packagefile;

				$packagefile = str_ireplace($this->replaceString, DS, $tempPackagefile);

				echo "<tr><td colspan=\"2\">Installing <b>".$instructions[0]."</b> to Joomla Instance <b>".$instructions[1]."</b></td></tr>";

				/*
				 * If $instructions[1] equals LOCAL the local installprocedure is startet
				 */
				if($instructions[1] == "LOCAL") {
					//This variable will contain the folders where the InstallerHelper extracts the fils
					$foldername = JInstallerHelper::unpack($packagefile);

					$extractdir = $foldername['extractdir'];
					$packagefile = $foldername['packagefile'];
					//Checks, if installation succeeded
					if(@$this->installer->install($extractdir))
					{
						echo "<tr><td><img src=\"./components/com_easiv2/images/true.png\" /></td><td valign=\"middle\"><b>Installation successful!</b></td></tr>";

						//set installed true in database
						$this->db->setQuery("UPDATE #__easiv2 SET installed = 'true' WHERE packagefile = '".str_ireplace(DS, $this->replaceString, $packagefile)."'");
						$this->db->query();
					}
					else
					{
						echo "<tr><td><img src=\"./components/com_easiv2/images/false.png\" /></td><td valign=\"middle\"><b>Installation failed!</b></td></tr>";
					}

					JFolder::delete($extractdir); //Deletes the extractfolders after the installation
				}
				else {
					/*
					 * Starting install process with FTP helper and XML-RPC call
					 */
					$ftpHelper = new FtpHelper();
					$ftpHelper->setPackage($packagefile);

					$this->remotePackageName = $ftpHelper->transferPackage($instructions[1]);

					if($this->remotePackageName != null) {
						$this->installRemote();
					}
					else {
						echo "transmission failed";
					}
				}
			}
			echo '</table>';
		}
		else {
			echo JText::_('Please select at least one package.');
		}
	}

	function installRemote() {

		$this->db->setQuery("SELECT http_address FROM #__easiv2_instances WHERE name ='".$this->instanceName."'");
		$instanceUrl = $this->db->loadObject()->http_address;
		$requestMethod = "manageExtensions.install";
		$request_param = xmlrpc_encode($this->remotePackageName);

		$postdata = http_build_query(
		array(
				'toInstall' => $request_param,
		)
		);

		$opts = array('http' =>	array(
					        'method'  => 'POST',
					        'header'  => 'Content-type: application/x-www-form-urlencoded',
							'content' => $postdata
		)
		);

		$context  = stream_context_create($opts);

		echo "installing remote on ".$instanceUrl;
		$response = file_get_contents($instanceUrl."/index.php?option=com_easiv2&task=".$requestMethod."&format=xmlrpc", false, $context);
			
		echo $response;
	}

	function uninstall()
	{
		for($i=0; $i < count($this->selectedPackages); $i++)
		{
			echo $this->selectedPackages[$i];
			$instructions = split(":", $this->selectedPackages[$i]);

			$this->instanceName = $instructions[1];
			$this->extensionName = $instructions[0];

			$this->db->setQuery("SELECT type FROM #__easiv2 WHERE extension = '".$instructions[0]."'");
				
			$type = $this->db->loadObject()->type;

			echo "Uninstalling <b>".$instructions[0]."</b> from Joomla Instance <b>".$instructions[1]."</b><br><br>";

			$this->db->setQuery("SELECT extension_id FROM #__extensions WHERE name ='".$instructions[0]."'");

			$extensionId = $this->db->loadObject()->extension_id;
				
			/**
			 *	Uninstallation Function.
			 */
			if($instructions[0] == "LOCAL") {
				if(@$this->installer->uninstall($type, $extensionId, 0)) {
					$this->db->setQuery("UPDATE #__easiv2 SET installed = 'false' WHERE extension = '".$extensionName."'");
					$this->db->query();
				}
			}
			else {
				$this->uninstallRemote();
			}
		}
	}

	function uninstallRemote() {
		$this->db->setQuery("SELECT http_address FROM #__easiv2_instances WHERE name ='".$this->instanceName."'");
		$instanceUrl = $this->db->loadObject()->http_address;

		$this->db->setQuery("SELECT type FROM #__easiv2 WHERE extension = '".$this->extensionName."'");
		$type = $this->db->loadObject()->type;


		$requestMethod = "manageExtensions.uninstall";
		$request_param = xmlrpc_encode($this->remotePackageName);

		$params = array($this->extensionName, $type);

		$request_params = xmlrpc_encode($params);


		$postdata = http_build_query(array(
        		'information' => $request_params,
			)
		);

		$opts = array('http' =>	array(
		        'method'  => 'POST',
		        'header'  => 'Content-type: application/x-www-form-urlencoded',
		        'content' => $postdata
			)
		);

		$context  = stream_context_create($opts);

		echo "installing remote on ".$instanceUrl;
		$response = file_get_contents($instanceUrl."/index.php?option=com_easiv2&task=".$requestMethod."&format=xmlrpc", false, $context);
			
		echo $response;
	}
}